// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	1/5/2014 9:51:29 PM				
// -----------------------------

#include "CMath.h"
#include "Vector4.h"
#include <math.h>
#include "Common.h"

const Float	Math::Pi = 3.14159265f;
const Float	Math::PiOver2 = 1.57079632f;
const Float	Math::PiTimes2 = 6.28318530f;
const Float	Math::PiOver4 = 0.78539816f;
const Float	Math::PiTimes4 = 12.56637061f;
const Float	Math::Epsilon = 0.00000001f;

UInt32 Math::s_uSeed = 0;

Float Math::Lerp(Float a, Float b, Float alpha)
{
	return (a + ((b - a) * alpha));
}
Float Math::Sin(Float fAngle)
{
	return sinf(fAngle);
}
Float Math::Cos(Float fAngle)
{
	return cosf(fAngle);
}
Float Math::Tan(Float fAngle)
{
	return tanf(fAngle);
}
Float Math::Sqrt(Float fValue)
{
	return sqrtf(fValue);
}
Float Math::Deg2Rad(Float fDegrees)
{
	return (fDegrees * (Math::Pi / 180.0f));
}
Float Math::Rad2Deg(Float fRadians)
{
	return (fRadians * (180.0f / Math::Pi));
}
Float Math::Abs(Float fValue)
{
	return fabsf(fValue);
}
Int32 Math::Abs(Int32 fValue)
{
	return abs(fValue);
}
Float Math::Pow(Float a, Float exp)
{
	return powf(a, exp);
}
Float Math::Pow(Float a, Int32 exp)
{
	return pow(a, exp);
}
Float Math::Min(Float a, Float b)
{
	return (a < b) ? a : b;
}
Float Math::Max(Float a, Float b)
{
	return (a > b) ? a : b;
}
UInt32 Math::Min(UInt32 a, UInt32 b)
{
	return (a < b) ? a : b;
}
UInt32 Math::Max(UInt32 a, UInt32 b)
{
	return (a > b) ? a : b;
}
Int32 Math::Min(Int32 a, Int32 b)
{
	return (a < b) ? a : b;
}
Int32 Math::Max(Int32 a, Int32 b)
{
	return (a > b) ? a : b;
}
Float Math::Clamp(Float a, Float min, Float max)
{
	return Math::Min(max, Math::Max(min, a));
}
Float Math::Floor(Float a)
{
	return floor(a);
}
Float Math::Ceil(Float a)
{
	return ceil(a);
}
Float Math::Mod(Float a, Float mod)
{
	return fmodf(a, mod);
}
Float Math::WrapUniform(Float a)
{
	Float val = Mod(a, 1.0f);
	if (val < 0.0f)
		return 1.0f - Math::Abs(val);
	return val;
}


UInt32 Math::SetSeed(UInt32 uSeed)
{
	if (uSeed == 0)
	{
		UInt64 cycles = 0;
		QueryPerformanceCounter((LARGE_INTEGER*)&cycles);
		s_uSeed = (UInt32)cycles;
	}
	else
		s_uSeed = uSeed;
	srand(s_uSeed);
	return s_uSeed;
}
UInt32 Math::GetSeed()
{
	return s_uSeed;
}
UInt32 Math::Random()
{
	return rand();
}
Int32 Math::Random(Int32 uMin, Int32 uMax)
{
	return uMin + (Random() % (uMax - uMin));
}
UInt32 Math::Random(UInt32 uMin, UInt32 uMax)
{
	return uMin + (Random() % ((uMax + 1) - uMin));
}
Float Math::RandomFloat(Float fMin, Float fMax)
{
	Float fAlpha = (Float) rand() / (Float)RAND_MAX;
	return (fMin + ((fMax - fMin) * fAlpha));
}
Vector4 Math::RandomPoint(Float fMinX, Float fMaxX, Float fMinY, Float fMaxY, Float fMinZ, Float fMaxZ)
{
	Vector4 v;
	v.x = RandomFloat(fMinX, fMaxX);
	v.y = RandomFloat(fMinY, fMaxY);
	v.z = RandomFloat(fMinZ, fMaxZ);
	v.w = 1.0f;
	return v;
}
Vector4 Math::RandomPoint(const Vector4& vMinPoint, const Vector4& vMaxPoint)
{
	Vector4 v;
	v.x = RandomFloat(vMinPoint.x, vMaxPoint.x);
	v.y = RandomFloat(vMinPoint.y, vMaxPoint.y);
	v.z = RandomFloat(vMinPoint.z, vMaxPoint.z);
	v.w = 1.0f;
	return v;

}